//////////////////////////////////////////////////////////////

//SOURCE FILE: colas.c

//PROCESO PLANIFICADOR DE DISCO

//Autor: Pablo Bergna

//////////////////////////////////////////////////////////////
#include "../includes/todo_incluido.h"
#include "../includes/colas.h"

/***********************************************************************
FUNCION: CREAR_COLA

PROCESO: PPD

Autor: Pablo Bergna

PRE:

POST: cola creada y con memoria alocada

DEVUELVE:	0 si salio bien
			-1 si hubo error al alocar memoria

FUNCION PPAL: crea una cola dado un puntero a cola sin memoria y un tamanio de bloques de datos para sus nodos
***********************************************************************/
uint8_t crear_cola(td_cola* cola, uint16_t tamanio_bloque){
	cola = (td_cola*)malloc(sizeof(td_cola));
	if (!(cola)) return -1;//ERROR AL ALOCAR MEMORIA
	cola->tam_bloque = tamanio_bloque;
	cola->entrada = NULL;
	cola->salida = NULL;
	return 0;
}

/***********************************************************************
FUNCION: COLA_VACIA

PROCESO: PPD

Autor: Pablo Bergna

PRE: *cola creada y alocada en memoria

POST: 	COLA_VACIA si no hay nodos en la cola
		COLA_NO_VACIA si hay algun nodo en la cola

DEVUELVE:

FUNCION PPAL: se fija si hay nodos en la cola agregados
***********************************************************************/
uint8_t cola_vacia (td_cola* cola){
	if ((cola->salida == NULL) && (cola->entrada == NULL)) return COLA_VACIA; //ESTA VACIA!
	return COLA_NO_VACIA;//NO ESTA VACIA!
}

/***********************************************************************
FUNCION: DESTRUIR_COLA

PROCESO: PPD

Autor: Pablo Bergna

PRE: *cola creada y alocada en memoria

POST: Elimina toda la cola y libera memoria

DEVUELVE:

FUNCION PPAL: elimina la cola y todos sus nodos (libera toda su memoria)
***********************************************************************/
void destruir_cola (td_cola* cola){
	while (cola_vacia(cola) == COLA_NO_VACIA){
		destruir_nodo(cola);
	}
	free(cola);
}

/***********************************************************************
FUNCION: DESTRUIR_NODO

PROCESO: PPD

Autor: Pablo Bergna

PRE: *cola creada y alocada en memoria

POST: Elimina al nodo salida de la cola

DEVUELVE:

FUNCION PPAL: elimina al nodo de salida de la cola (y libera su memoria)
***********************************************************************/
void destruir_nodo(td_cola* cola){
	td_nodo_cola* aux;

	if (cola_vacia(cola) == COLA_VACIA) return;
	aux= cola->salida;//GUARDA EL QUE SERA ELIMINADO
	cola->salida = cola->salida->proximo;//LA COLA APUNTA AL NUEVO SALIDA
	free(aux->datos);//LIBERA LOS DATOS DEL NODO
	free(aux);//LIBERA LA ESTRUCTURA DEL NODO
}

/***********************************************************************
FUNCION: AGREGAR_NODO

PROCESO: PPD

Autor: Pablo Bergna

PRE: *cola creada y con memoria alocada, *datos conteniendo estructura del tamaño de bloque

POST: Agrega a la cola (al final) el nodo conteniendo *datos

DEVUELVE: 	0 si salio bien
			-1 si hubo error al alocar memoria

FUNCION PPAL: agrega un nodo a la cola
***********************************************************************/
uint8_t agregar_nodo(td_cola* cola, void* datos){
	td_nodo_cola* aux;

	aux = (td_nodo_cola*)malloc(sizeof(td_nodo_cola));
	if (!(aux)) return -1;//SI FALLA AL ALOCAR MEMORIA
	aux->datos = (void*)malloc(cola->tam_bloque);
	if (!(aux->datos)){
		free(aux);
		return -1;//SI FALLA AL ALOCAR MEMORIA
	}
	//LLENADO DE DATOS
	memcpy(aux->datos,datos,cola->tam_bloque);
	aux->proximo = NULL;

	if (cola_vacia(cola) == COLA_VACIA) cola->salida = aux;//POR LA PRIMERA VEZ QUE SE AGREGAN DATOS

	//ENCOLADO DE NUEVO NODO
	if (cola->entrada != NULL){
		cola->entrada->proximo = aux;
	}
	cola->entrada = aux;

	return 0;//SALIO TODO BIEN
}

/***********************************************************************
FUNCION: SACAR_NODO

PROCESO: PPD

Autor: Pablo Bergna

PRE: *cola creada y con memoria alocada

POST: devuelve en *datos lo que contenía el nodo de salida de la cola, SACANDO AL NODO DE LA COLA

DEVUELVE: 	0 si salio bien
			-1 si hubo error al alocar memoria
			-2 si la cola está vacía (no aloca memoria para *datos)

FUNCION PPAL: copia los datos del nodo de salida en el puntero *datos (y le asigna memoria)
***********************************************************************/
uint8_t sacar_nodo(td_cola* cola, void* datos){

	if (cola_vacia(cola) == COLA_VACIA) return -2;
	datos = (void*)malloc(cola->tam_bloque);
	if (!(datos)) return -1;//SI FALLA AL ALOCAR MEMORIA

	//COPIA DE DATOS
	memcpy(datos,cola->salida->datos,cola->tam_bloque);

	destruir_nodo(cola);//ELIMINA AL NODO DE SALIDA

	return 0;//SALIO TODO BIEN
}

/***********************************************************************
FUNCION: OBTENER_NODO

PROCESO: PPD

Autor: Pablo Bergna

PRE: *cola creada y con memoria alocada

POST: devuelve en *datos lo que contenía el nodo de salida de la cola, SIN SACARLO DE LA COLA

DEVUELVE: 	0 si salio bien
			-1 si hubo error al alocar memoria
			-2 si la cola está vacía (no aloca memoria para *datos)

FUNCION PPAL: copia los datos del nodo de salida en el puntero *datos (y le asigna memoria)
***********************************************************************/
uint8_t obtener_nodo(td_cola* cola, void* datos){

	if (cola_vacia(cola) == COLA_VACIA) return -2;
	datos = (void*)malloc(cola->tam_bloque);
	if (!(datos)) return -1;//SI FALLA AL ALOCAR MEMORIA

	//COPIA DE DATOS
	memcpy(datos,cola->salida->datos,cola->tam_bloque);

	return 0;//SALIO TODO BIEN
}
